﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BattleAtms.Models;

namespace BattleAtms.Helpers
{
    public static class GameHelper
    {
        private const int MAX_SHIP_SIZE = 4;
        private const int MIN_SHIP_SIZE = 1;
        private const int BOARD_SIZE = 10;

        static Random _random = new Random();

        public static ICollection<Ship> GenerateShips()
        {
            var ships = new List<Ship>();
            var cells = new List<Cell>();
            for (int shipSize = MAX_SHIP_SIZE; shipSize >= MIN_SHIP_SIZE; shipSize--)
            {
                int MAX_SHIP_COUNT = 1 + MAX_SHIP_SIZE - shipSize;
                for (int shipNo = 0; shipNo < MAX_SHIP_COUNT; shipNo++)
                {
                    while (true)
                    {
                        Ship ship = CreateRandomShip(shipSize);
                        if (IsShipFit(ship, cells))
                        {
                            ships.Add(ship);
                            cells.AddRange(ship.Decks);
                            break;
                        }
                    }
                }
            }
            return ships;
        }

        private static Ship CreateRandomShip(int shipSize)
        {

            int x = 0;
            int y = 0;
            int endX = int.MaxValue;
            int endY = int.MaxValue;
            int xIncrement = 0;
            int yIncrement = 0;
            while (endX >= BOARD_SIZE || endY >= BOARD_SIZE || endX < 0 || endY < 0)
            {
                x = _random.Next(BOARD_SIZE);
                y = _random.Next(BOARD_SIZE);
                int direction = _random.Next(4);
                switch (direction)
                {
                    case 0:
                        endX = x + shipSize;
                        endY = y;
                        xIncrement = 1;
                        break;
                    case 1:
                        endX = x - shipSize;
                        endY = y;
                        xIncrement = -1;
                        break;
                    case 2:
                        endX = x;
                        endY = y + shipSize;
                        yIncrement = 1;
                        break;
                    case 3:
                        endX = x;
                        endY = y - shipSize;
                        yIncrement = -1;
                        break;
                }
            }
            Ship ship = new Ship();
            for (int i = 0; i < shipSize; i++, x += xIncrement, y += yIncrement)
            {
                ship.Decks.Add(new Cell { State = CellState.Filled, X = x, Y = y });
            }
            return ship;
        }

        private static bool IsShipFit(Ship ship, ICollection<Cell> cells)
        {
            foreach (var deck in ship.Decks)
            {
                if (!IsDeckFit(deck, cells))
                {
                    return false;
                }
            }
            return true;
        }

        private static bool IsDeckFit(Cell deck, ICollection<Cell> cells)
        {
            for (int x = deck.X - 1; x <= deck.X + 1; x++)
            {
                for (int y = deck.Y - 1; y <= deck.Y + 1; y++)
                {
                    if (cells.AsQueryable().Count(c => c.X == x && c.Y == y) > 0)
                    {
                        return false;
                    }
                }
            }
            return true;
        }

    }
}